/*********************************************************************************
 *      Copyright:  (C) 2022 zengwen<1825984037@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  get_data.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(26/04/22)
 *         Author:  zengwen <1825984037@qq.com>
 *      ChangeLog:  1, Release initial version on "26/04/22 13:17:51"
 *                 
 ********************************************************************************/
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <sys/types.h>
#include <libgen.h>  
#include <asm/byteorder.h>
#include <stdarg.h>
#include "logger.h"
#include "sqlite3.h"
	
int get_temID (char SN[]);
int get_time(char cur_time[]);
int socket_client_init(char *ip,int port);
int socket_client_write(int sockfd,char massage[]);
int open_data_sqlite (sqlite3 **db);
int save_data_sqlite(sqlite3 *db,char Data[]);
int get_data_sqlite(sqlite3 *db,char Data[]);
int delete_data_sqlite(sqlite3 *db);
void print_usage(char *progname);
void sig_handle(int signum);

int get_stop=0;


int main (int argc, char **argv)
{
	char                 SN[128];
	int                  rv;
	int                  ch;
	int                  port=0;
	char                 *ip = NULL;
	int                  daemon_run=0;
	char                 Data[256];
	char                 Buf[256];
	char                 massage[256];
	int                  sockfd=-1;
	struct sockaddr_in   sockaddr;
	int                  time;
	char                 cur_time[64];
	char                 data;
	char                *progname=NULL;
	sqlite3             *db;
	struct tcp_info      info;
	int                  len=sizeof(info);
    struct option        opts[]={
		{"port",required_argument,NULL,'p'},
		{"ip",required_argument,NULL,'i'},
		{"time",required_argument,NULL,'t'},
		{"hlep",no_argument,NULL,'h'},
		{NULL,0,NULL,0}
	};

	progname = basename(argv[0]);

	while((ch=getopt_long(argc,argv,"p:i:t:h",opts,NULL))!=-1)
	{
		switch(ch)
		{
			case 'p':
				port=atoi(optarg);
				break;
			case 'i':
				ip=(optarg);
				break;
			case 't':
				time=atoi(optarg);
				break;
			case 'h':
				print_usage(argv[0]);
				return 0;
			default:
				break;
		}
	}
	
	if(!port||!ip||!time)
	{
		print_usage(progname);
		return 0;
	}
	
	//信号捕捉
	/*signal(SIGINT,sig_handle);
	 *signal(SIGALRM,sig_handle);
	signal(SIGTERM,sig_handle);*/

	//日志
	rv =  logger_init("/home/zengwen/client.log", LOG_LEVEL_MAX, 1024) ;
	if(rv < 0 )
	{
		fprintf(stderr,"initial logger failure:%s\n",strerror(errno));
		return -1;
	}
	log_info("Logger system initialise ok\n");
	
	if(open_data_sqlite(&db))
	{
		printf("open database failure:%s\n",strerror(errno));

		return -2;
	}
	log_info("open database succesfully!\n");

	sockfd=socket_client_init(ip,port);
	
	while(1)
	{
		rv=get_temID(SN);
	 	if(rv<0)
		{
			printf("get temperature and pie_ID failure,rv=:%d\n",rv);
			return -1;
		}
		log_info("SN=%s\n",SN);

		memset(Data,0,sizeof(Data));
		get_time(cur_time);
		printf ("SN=%s\n",SN);
        snprintf(Data,sizeof(Data),"%s/%s",SN,cur_time);
    	log_info("Data is %sC\n",Data);

		//if(sockfd>0)//客户端已连接服务器
		getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
		if(info.tcpi_state == TCP_ESTABLISHED) 
		{
			if(socket_client_write(sockfd,Data)<0)//发送数据失败
			{
				printf("send realtime data failure:%s\n",strerror(errno));
				if(save_data_sqlite(db,Data)<0)//保存到数据库
				{
					log_err("insert data failure:%s\n",strerror(errno));
				}
				log_info("sava data to database succesfully\n");
			}

			memset(Buf,0,sizeof(Buf));
			if(get_data_sqlite(db,Buf)==0)//获取数据库保存的数据成功
			{
				printf("数据库获取的数据：%s\n",Buf);
				if(0==socket_client_write(sockfd,Buf))//发送数据
				{
					log_info("send data from database succesfully\n");
					if(delete_data_sqlite(db)<0)
					{
						log_err("delete data from databases failure:%s\n",strerror(errno));
					}
					else
					{
						log_info("delete data from database successfully\n");
					}
				}
				else//发送数据失败
				{
					log_err("send data from database failure:%s\n",strerror(errno));
					close(sockfd);
				}
			}
			else//获取数据库数据失败
			{
				 log_err("database has no data\n");
			}
		}
		else//客户端未连接服务器
		{
			if((socket_client_init(ip,port))<0)//重连失败
			{
				 printf("connect to server again failure:%s\n",strerror(errno));
				  if(save_data_sqlite(db,Data)<0)//保存到数据库
				  {
					   printf("insert data to database failure:%s\n",strerror(errno));
				  }
				  else
				  {
					   printf("insert data to database succesfully\n");
				  }
				  close(sockfd);
			 }
			 else//重连成功
			 {
				 log_info("connect to server succesfully again!\n");
			 }
		}
		logger_term();
		sleep(time);
	}
	close(sockfd);
	sqlite3_close( db );
	return 0;
//	printf("power off gprs\n");
}

//创建socket
int socket_client_init(char *ip,int port)
{
	int                  sockfd=-1;
	int                  confd=-1;
	struct sockaddr_in   sockaddr;
	char                 buf[1024];
	char                 massage[128];
	float                temp;
	char                 pie_ID[128];
	char                 cur_time[20]={0};
	int                  rv_read;

	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		log_err("Create sockfd %d failure:%s\n",sockfd,strerror(errno));
		return -2;
	}
	log_info("Create sockfd %d succesfully!\n",sockfd);

    memset(&sockaddr,0,sizeof(sockaddr));
	sockaddr.sin_family=AF_INET;
	sockaddr.sin_port=htons(port);
	inet_aton(ip,(void *)&sockaddr.sin_addr);
	confd=connect(sockfd,(struct sockaddr *)&sockaddr,sizeof(sockaddr));
	if(confd<0)
	{
		log_err("connect to server [%s:%d] failure:%s\n",ip,port,strerror(errno));
		return -3;
	}
	log_info("connect to server [%s:%d] succesfully!\n",ip,port);
	return sockfd;
}

int socket_client_write(int sockfd,char massage[])
{
	int  rv;
	char buf[128];

	if(write(sockfd,massage,strlen(massage))<0)
	{
		printf ("Write data to server failure:%s\n",strerror(errno));
		return -4;
	}
	printf ("Write data to server succesfully!\n");
#if  0

	memset(&buf,0,sizeof(buf));
	rv=read(sockfd,buf,sizeof(buf));
	if(rv<0)
	{
		printf ("Read data from server failure:%s\n",strerror(errno));
		goto cleanup;
	}
	else if(rv==0)
	{
		printf("Client connect to server get disconnected!\n");
		goto cleanup;
	}
	printf("Read %d bytes data from server:%s\n",rv,buf);
#endif

	return 0;
} 


int get_temID (char SN[])
{
	float           temp;
	char            pie_ID[128];
	DIR            *dirp=NULL;
	struct dirent  *redir=NULL;
	int             found=0;
	char            buf[128];
	char            ID[128];
	char            path[128]="/sys/bus/w1/devices/";
	int             fd;
	char           *ptr=NULL;


	dirp=opendir(path);
	if(!dirp)
	{
		printf ("open file %s failure:%s\n",path,strerror(errno));
		return -1;
	}

	 while(NULL!=(redir=readdir(dirp)))
	 {
		 if(strstr(redir->d_name,"28-"))
		 {
			 strncpy(ID,redir->d_name,sizeof(ID));
			 found=1;
		 }
	 }

	 closedir(dirp);
	 if(!found)
	 {
		 printf ("can not find this dirent:%s\n",strerror(errno));
		 return -2;
	 }

	 strncat(path,ID,sizeof(path)-strlen(path));
	 strncat(path,"/w1_slave",sizeof(path)-strlen(path));

	 printf ("PATH=%s\n",path);

	 if((fd=open(path,O_RDONLY))<0)
	 {
		 printf ("open fd=%d failure:%s\n",fd,strerror(errno));
		 return -3;
	 }

	 memset(buf,0,sizeof(buf));
	 if((read(fd,buf,sizeof(buf)))<0)
	 {
		  printf ("read fd=%d failure:%s\n",fd,strerror(errno));
		  return -4;
	 }

	 ptr=strstr(buf,"t=");
	 if(ptr==NULL)
	 {
		 printf ("can not find t= string\n");
		 return -5;
	 }
	 
	 ptr+=2;
	 temp=atof(ptr)/1000;

	 snprintf(SN,128,"%s/%f",ID,temp);

	 close(fd);
	 return 0;
} 

int get_time(char cur_time[])
{
	time_t timep;
	struct tm *p;

	time(&timep);

	p = gmtime(&timep);
	snprintf(cur_time, 20, "%d.%d.%d %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
	return 0;
}

//打开数据库
int open_data_sqlite (sqlite3 **db)
{
	int         ret;
	char       *errmsg = 0;


	ret=sqlite3_open("RPI.db",db);//打开当前路径下的RPI.db数据库标识
	if(ret!=SQLITE_OK)
	{
		log_err("Failed to open database!:%s\n",sqlite3_errmsg(*db));
		return -1; 
	}
	else
	{
		log_info("Open database sucessfuly!\n");
	}
	char  *sql="CREATE TABLE IF NOT EXISTS sendata(\
				ID INTEGER PRIMARY KEY AUTOINCREMENT,\
				SN       TEXT,\
				TM       TEXT,\
				TEMP     TEXT\
				);";
	ret=sqlite3_exec(*db,sql,NULL,NULL,&errmsg);
	if(ret != SQLITE_OK)
	{
		log_err("Create table error:%s\n",errmsg);
    	sqlite3_free(errmsg);
	    return -2;
	}
	log_info("Table create successfully\n");
	return 0;
}

//保存数据到数据库
int save_data_sqlite(sqlite3 *db,char Data[])
{
	char                *SN;
	char                *TM;
	char                *TEMP;
	char                 sql_in[256];
	int                  rv=0;
	char                *errmsg=0;
	const char           s[2] = "/";


	SN=strtok(Data, s);
	TM=strtok(NULL,s);
	TEMP=strtok(NULL,s);

	sprintf(sql_in, "INSERT INTO sendata(SN,TM,TEMP) VALUES('%s', '%s','%s');", SN,TM,TEMP);//构造sqlite语句

	rv=sqlite3_exec(db,sql_in,NULL,NULL,&errmsg);
	if (rv == SQLITE_OK)
		{
			 log_info("Insert data OK! rv=%d\n", rv);
		}
	else
	{
		 log_err("Insert data Error!%s\n", strerror(errno));
		 sqlite3_free(errmsg);
	}
	return 0;
}

//获取数据库保存的数据
int get_data_sqlite(sqlite3 *db,char Buf[])
{
	int           rv=-1;
	char         *sql="SELECT * FROM sendata LIMIT 1;";
	const char   *error=NULL;
	sqlite3_stmt *pstmt;
	int           nCol = 1;
	char         *sn;
	char         *time;
	char         *temp;


	rv = sqlite3_prepare_v2(db, sql, strlen(sql), &pstmt, &error);
	if( rv < 0 )
	{
		log_err("get tables failue:%s\n",strerror(errno));
	}
	if(sqlite3_step( pstmt ) == SQLITE_ROW)
	{
		sn= (char *)sqlite3_column_text(pstmt,1); 
		temp= (char *)sqlite3_column_text(pstmt,2); 
		time=(char *)sqlite3_column_text(pstmt,3); 
	}
		snprintf(Buf,strlen(time)*6,"%s/%s/%s",sn,temp,time);

		return 0;
}

//删除数据库已发送的数据
int delete_data_sqlite(sqlite3 *db)
{
	int   rv = -1; 
	char  *error = NULL;
	char  *sql = "delete from  sendata where rowid in (select rowid from sendata LIMIT 1);";
	rv = sqlite3_exec(db, sql, NULL, NULL, &error);
	if( rv < 0)
	{
		printf("delete data form table failure:%s\n",strerror(errno));
		sqlite3_free(error);
		return -1; 
	}
	log_info("delece a record.\n");
	return 0;
}

//安装信号
void sig_handle(int signum)
{
	printf("catch signal[%d]\n",signum);
	get_stop=1;
}

//参数解析
void print_usage(char *progname)
{
	printf ("%s usage:\n",progname);
	printf("-i(--ipaddr):sepcify server IP address\n");
	printf("-p(--port):sepcify server listen port.\n");
	printf ("-t(--time):sepcify report time\n");
	printf("-b(--daemon):set program runing on background\n");
	printf("-h(--help):print this help information.\n");
	
	return ;
}
